﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using DBAccessLibrary.Common;
using DBAccessLibrary;
using QueryResource.Common;
using DBAccessLibrary.Model;
using System.Threading.Tasks;
using QueryResource.TextFormat;
using System.Windows.Media;

namespace QueryResource.ViewModel
{
    public class SqlViewModel : BasePropertyChange
    {
        private SqlCustomAnalyzer _analyzer;         //分词

        public SqlViewModel()
        {
            this.ExecSqlCommand = new DelegateCommand<string>(sqlArray =>
            {
                Action action = () =>
                {
                    try
                    {
                        List<string> sqlList = new List<string>();
                        //如果是存储过程 则认为是一句命令
                        //替换多余空格
                        Regex r = new Regex(@" {2,}", RegexOptions.Multiline);
                        if (r.IsMatch(sqlArray))
                        {
                            sqlArray = r.Replace(sqlArray, " ");
                        }
                        if (sqlArray.StartsWith("CREATE PROCEDURE ", StringComparison.CurrentCultureIgnoreCase))
                        {
                            sqlList.Add(sqlArray);
                        }
                        else
                        {
                            foreach (string sql in sqlArray.ToFilterKeyword(";"))
                            {
                                if (sql == string.Empty)
                                    continue;
                                if (sql.StartsWith("CREATE", StringComparison.CurrentCultureIgnoreCase) ||
                                    sql.StartsWith("UPDATE", StringComparison.CurrentCultureIgnoreCase) ||
                                    sql.StartsWith("INSERT", StringComparison.CurrentCultureIgnoreCase) ||
                                    sql.StartsWith("DELETE", StringComparison.CurrentCultureIgnoreCase) ||
                                    sql.StartsWith("ALTER", StringComparison.CurrentCultureIgnoreCase) ||
                                    sql.StartsWith("WITH", StringComparison.CurrentCultureIgnoreCase) ||
                                    sql.StartsWith("DROP", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    sqlList.Add(sql);

                                }
                                else
                                {
                                    WriteData(sql);
                                }
                            }
                        }
                        if (sqlList.Count > 0)
                        {
                            this.ExecSql(sqlList);
                        }
                    }
                    catch (Exception ex)
                    {
                        WriteLog(ex.Message, Colors.Red);
                    }
                };
                Task.Factory.StartNew(action);
            });

            this.F5Command = new DelegateCommand(() => ExecSqlCommand.Execute(this.SelectText), () => string.IsNullOrEmpty(this.SelectText));
        }

        /// <summary>
        /// 执行SQL 命令
        /// </summary>
        public DelegateCommand<string> ExecSqlCommand { get; set; }

        /// <summary>
        /// 执行命令
        /// </summary>
        public DelegateCommand F5Command { get; set; }
        public string SelectText
        {
            get
            {
                if (GetSelectText != null)
                {
                    return GetSelectText();
                }
                return string.Empty;
            }
            set
            {
                if (SetSelectText != null)
                {
                    SetSelectText(value);
                }
            }
        }
        private string FontName
        {
            get
            {
                if (GetFontName != null)
                {
                    return GetFontName();
                }
                return string.Empty;
            }
        }
        private double FontSize
        {
            get
            {
                if (GetFontSize != null)
                {
                    return GetFontSize();
                }
                return 0;
            }
        }
        private double MaxWidth
        {
            get
            {
                if (GetMaxWidth != null)
                {
                    return GetMaxWidth();
                }
                return 0;
            }
        }

        /// <summary>
        /// 换行 添加信息到末尾 并执行
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="status"> </param>
        public void ExecAppendCmd(string msg, SqlControlStatus status)
        {
            string sql = SqlFormatPainter(msg,false);
           SqlControlStatus newline = status & SqlControlStatus.NewLine;
           WriteText(newline == SqlControlStatus.NewLine ? Environment.NewLine + sql : sql);
           if ((status & SqlControlStatus.Run) == SqlControlStatus.Run)
            {
                this.ExecSqlCommand.Execute(msg);
            }
        }

        /// <summary>
        /// 当输入点时触发
        /// </summary>
        /// <param name="content"></param>
        /// <param name="caretoffice"></param>
        /// <returns></returns>
        public TableEntity TextEnteredPoint(string content, int caretoffice)
        {
            if (SysCache.TableList == null)
                return null;

            //查找出关键字
            string sql = content.Substring(0,caretoffice).Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ");

            //截取最后一个空格所在位置
            //主要是判断 如果直接是表名 的情况
            List<int> list = new List<int>{
                sql.LastIndexOf(' '),
                sql.LastIndexOf(','),
                sql.LastIndexOf('='),
                sql.LastIndexOf('(')
            };
            int lastindex = list.Max();
            string key = lastindex > 0 ? sql.Substring(lastindex + 1, sql.Length - lastindex - 2) : sql.Remove(sql.Length-1);
            if (key.IndexOf('\'') >= 0)
                return null;
            //首先 判断 key 是否就是表名
            TableEntity tableentity = SysCache.TableList.FirstOrDefault(o => o.TransName.ToUpper() == key.ToUpper());
            if (tableentity != null)
                return tableentity;
            //可能存在内容 包含； 的情况。所以这里不能根据；判断
            sql += content.Substring(caretoffice);
           
         
            //分词检索表名
            if (_analyzer == null)
                _analyzer = new SqlCustomAnalyzer();
            string tableName = _analyzer.AnalyzerFunc(sql, key, lastindex);

            string[] equalArray = new[]
                                      {
                                          key.Replace("[", "").Replace("]", "").Trim().ToUpper(),
                                          tableName.Replace("[", "").Replace("]", "").Trim().ToUpper()
                                      };
            //检索表实体
            TableEntity table = SysCache.TableList.FirstOrDefault(o => equalArray.Contains(o.TransName.ToUpper()));
            return table;
        }
       
        /// <summary>
        /// 当输入空格时触发
        /// </summary>
        /// <param name="content"></param>
        /// <param name="caretoffice"></param>
        /// <returns></returns>
        public IEnumerable<DataBaseEntity> TextEnteredSpace(string content, int caretoffice)
        {
            //查找出关键字
            string sql = content.Substring(0, caretoffice);
            int offset = sql.TrimEnd().LastIndexOf(' ');
            try
            {
                string key = sql.Substring(offset + 1).Split(new[] { Environment.NewLine,"\n" }, StringSplitOptions.RemoveEmptyEntries).Last().ToUpper();
                List<DataBaseEntity> list = new List<DataBaseEntity>();
                if (key.Trim() == "FROM" || 
                    key.Trim() == "DELETE" || 
                    key.Trim() == "UPDATE" ||
                    key.Trim() == "JOIN")
                {
                    if (SysCache.TableList != null)
                        return SysCache.TableList;
                    return list;
                }
               
                if ((key.Trim().StartsWith("EXEC") && SysCache.DBConnection.ConnectType != DBType.DB2) ||
                    (key.Trim().StartsWith("CALL") && SysCache.DBConnection.ConnectType == DBType.DB2))
                {
                    //存储过程 和 视图
                    if (SysCache.ProcList != null)
                        list.AddRange(SysCache.ProcList);
                    if (SysCache.ProcList != null)
                        list.AddRange(SysCache.ProcList);
                    return list;
                }
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message, Colors.Red);
            }
            return null;
        }
        /// <summary>
        /// 当输入逗号时触发
        /// </summary>
        /// <param name="content"></param>
        /// <param name="caretoffice"></param>
        /// <returns></returns>
        public IEnumerable<DataBaseEntity> TextEnteredComma(string content, int caretoffice)
        {
            if (SysCache.TableList == null)
                return null;

            //查找出关键字
            string sql = content.Substring(0, caretoffice).ToLower();

            //主要是判断 如果直接是表名 的情况
            List<int> list = new List<int>{
                sql.LastIndexOf("select "),
                sql.LastIndexOf(" from "),
                sql.LastIndexOf(" join "),
                sql.LastIndexOf(" where ")
            };
            int max = list.Max();
            if (max == list[1] || max ==list[2])
            {
                return SysCache.TableList;
            }
            return null;
        }
        /// <summary>
        /// 格式化选择的文本
        /// </summary>
        public string SqlFormatPainter(string text,bool isReplaceNewLine)
        {
            //换行和去除多余空格
            //string sql = SQLFormatPainter(this.SelectText,isReplaceNewLine);
            //根据不同数据库 修改 时间格式数据
            //sql = SQLFormatDate(sql.TrimEnd());
            //this.SelectText = sql;
            try
            {
                FormatMaster format = new FormatMaster();
                format.AddTextFormat(new ReplaceSpaceFormat(isReplaceNewLine));
                format.AddTextFormat(new DateStatusFormat());
                format.AddTextFormat(new AutoNewLineFormat(this.MaxWidth, this.FontName, this.FontSize));
                format.AddTextFormat(new IsNullFormat());
                return format.TextFormat(text);
            }
            catch(Exception ex)
            {
                WriteLog(ex.Message, Colors.Red);
                return text;
            }
        }

        #region 外界通知
        public Action<string, Color> AppendLogAction
        {
            private get;
            set;
        }
        public Action<string> AppendDataAction
        {
            private get;
            set;
        }

        public Action<string> AppendText
        {
            private get;
            set;
        }
        public Action<string> SetSelectText { get; set; }
        public Func<string> GetSelectText { get; set; }
        public Func<string> GetFontName { get; set; }
        public Func<double> GetFontSize { get; set; }
        public Func<double> GetMaxWidth { get; set; }
        private void WriteLog(string msg, Color isError)
        {
            if (AppendLogAction != null)
            {
                AppendLogAction(msg, isError);
            }
        }
        private void WriteData(string sql)
        {
            if (AppendDataAction != null)
            {
                AppendDataAction(sql);
            }
        }
        private void ExecSql(List<string> sqls)
        {
            try
            {
                int count = sqls.Count();
                for (int i = 0; i < count; i++)
                {

                    object result = DBOperatorFactory.GetOperator.ExecNonQuery(sqls[i]);
                    WriteLog(string.Format("执行成功,返回:{0}.{1}/{2}",result,i+1,count), Colors.Blue);
                }
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message, Colors.Red);
                string msg = DBOperatorFactory.GetGrammar(SysCache.DBConnection).GetErrorInfo(ex.Message);
                if (msg != string.Empty)
                    WriteLog(msg, Colors.Red);
            }
        }

        private void WriteText(string text)
        {
            if (AppendText != null)
            {
                AppendText(text);
            }
        }

        #endregion

        public bool IsPositionTable
        {
            get
            {
                //检索表实体
                TableEntity table = SysCache.TableList.FirstOrDefault(o => o.Name.Equals(this.SelectText, StringComparison.CurrentCultureIgnoreCase) || o.ChName.Equals(this.SelectText, StringComparison.CurrentCultureIgnoreCase));
                return table != null;
            }
        }
        /// <summary>
        /// 定位到表
        /// </summary>
        public void PositionTable()
        {
            string txt = this.SelectText.Trim();
            if (SysCache.TableList == null)
            {
                WriteLog("当前数据源还没初始化好，无法进行定位。", Colors.Red);
                return;
            }
            //检索表实体
            DataBaseEntity table = SysCache.TableList.FirstOrDefault(o => o.Name.Equals(txt, StringComparison.CurrentCultureIgnoreCase) || o.ChName.Equals(txt, StringComparison.CurrentCultureIgnoreCase));
            if (table == null)
            {
                //检索列
                List<TableEntity> root = SysCache.TableList.Where(o => o.FileNodes.FirstOrDefault(p => p.Name.Equals(txt, StringComparison.CurrentCultureIgnoreCase) || p.ChName.Equals(txt, StringComparison.CurrentCultureIgnoreCase)) != null).ToList();
                int count = root.Count;
                if(count > 0)
                {
                    table = root[0];
                }
                if( count > 1)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("找到" + count + "个符合要求的列");
                    for(int i=1;i<count;i++)
                    {
                        sb.AppendLine(root[i].Name + "-->" + txt);
                    }
                    WriteLog(sb.ToString(),Colors.Blue);
                }
            }
            
            if (table != null)
            {
                DataBaseEntity server = SysCache.ServerList.FirstOrDefault(o => o.Name == SysCache.DBConnection.Server);
                if(server != null)
                {
                    DataBaseEntity db =server.ChildNodes.FirstOrDefault(o => o.Name == SysCache.DBConnection.DataBase);
                    if(db != null && db.ChildNodes.Count >0)
                    {
                        db.ChildNodes[0].IsExpanded = true;
                    }
                }
                table.IsExpanded = true;
                if (table.IsSelected)
                    table.IsSelected = false;
                table.IsSelected = true;
            }
        }


        /// <summary>
        /// 给SQL 2边加入 引号
        /// </summary>
        /// <returns></returns>
        public void SqlSplicePainter()
        {
            string sql = this.SelectText;
            if (sql == string.Empty)
                return ;

           
           
            string[] splits = sql.Split(new [] { Environment.NewLine,"\n","\r" }, StringSplitOptions.RemoveEmptyEntries);
            StringBuilder sb = new StringBuilder();
            foreach (string s in splits)
            {
                sb.Append("\" ");
                string sqlStr = s;
                if (s.TrimStart()[0] == '"')
                {
                    sqlStr = sqlStr.Remove(sqlStr.IndexOf('"'), 1);
                }
                sb.Append(sqlStr.Replace("\" +\"", "").Replace("\" + \"", "")
                            .Replace("\t \"", "").Replace("\t\"", "")
                            .Replace("\" +", "").Replace("\"+", "")
                            .Replace("+\"", "").Replace("+ \"", "")
                            .Replace("\";", ""));
                sb.Append("\" +" + Environment.NewLine);
            }
            this.SelectText = sb.ToString();
        }
    }

}
